﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;

namespace Agr.CQRS.Infrastructure.Orm
{
    /// <summary>
    /// orm wrapper: opens session plus transaction
    /// </summary>
    public class SessionInTransaction : IDisposable
    {
        public ISession Session;
        private ITransaction tx;

        public SessionInTransaction(ISessionFactory sessionFactory)
        {
            Session = sessionFactory.OpenSession();
            Session.FlushMode = FlushMode.Commit;
            tx = Session.BeginTransaction();
        }

        /// <summary>
        /// commit transaction and dispose session
        /// </summary>
        public void Commit()
        {
            tx.Commit();
            tx.Dispose();
            tx = null;
        }

        /// <summary>
        /// create new object (example: query) that uses this session
        /// </summary>
        public T UseIn<T>() where T : IOrmSessionAware, new()
        {
            return new T { Tx = this };
        }

        /// <summary>
        /// get object by id and throw exception if it doesn't exist
        /// </summary>
        public T GetExisting<T>(int id)
        {
            var retval = Session.Get<T>(id);
            if (retval == null)
                throw new ArgumentException(typeof(T).Name + " niet gevonden met id " + id);
            return retval;
        }

        /// <summary>
        /// get object by id and return null if it doesn't exist
        /// </summary>
        public T Get<T>(int id)
        {
            return Session.Get<T>(id);
        }

        public void Insert(object o)
        {
            Session.Save(o);
        }

        /// <summary>
        /// create nhibernate proxy object for object with given id
        /// </summary>
        public T Load<T>(int id)
        {
            return Session.Load<T>(id);
        }

        #region IDisposable Members

        public void Dispose()
        {
            if (tx != null)
            {
                tx.Rollback();
                tx.Dispose();
            }
            if (Session != null)
                Session.Dispose();

            tx = null;
            Session = null;
        }

        #endregion
    }
}
